<?php

namespace common\services\myhtsq;

use common\entities\ContractEntity;
use common\error\ErrorCode;
use common\error\ErrorInfo;
use common\models\myhtsq\ContractReceivableModel;
use common\models\myhtsq\DocumentModel;
use common\repositories\myhtsq\ContractEmailContactsRepository;
use common\repositories\myhtsq\ContractManageRepository;
use common\repositories\myhtsq\DocumentRepository;
use common\repositories\myhtsq\ErpUserRepository;
use common\services\BaseService;
use common\models\myhtsq\InvoiceSummaryModel;
use common\repositories\myhtsq\ContractReceivableRepository;
use common\repositories\myhtsq\InvoiceRepository;
use common\repositories\myhtsq\InvoiceSummaryRepository;
use common\repositories\myhtsq\InvoiceReceivableRepository;
use common\repositories\myhtsq\InvoicePaymentRepository;
use common\services\common\EmailService;
use common\services\common\MyscrmContractSyncDeleteDataService;
use yii\base\Exception;
use common\entities\myhtsq\ContractReceivableEntity;

/**
 * Description of ContractReceivable
 * 合同应收款管理服务
 * @author chenxc
 */
class ContractReceivableService extends BaseService {

    public function __construct($config = array()) {
        parent::__construct($config);
    }

    /**
     * 根据合同ID获取对应的应收款项明细
     * @param string $contractId 合同id
     * @param boolean $withBadDebt 是否包含坏账
     * @return array
     */
    public function getReceivableInfoByContractId($contractId, $withBadDebt = true) {
        return ContractReceivableRepository::getReceivableInfoByContractId($contractId, $withBadDebt);
    }

    /**
     * 获取指定合同下的所有应收款金额
     * @param string $contractId 合同id
     * @return float 
     */
    public function getReceivableTotalAmountByContractId($contractId) {
        return ContractReceivableRepository::getReceivableTotalAmountByContractId($contractId);
    }

    /**
     * 保存合同应收款项
     * @param \common\models\myhtsq\ContractReceivableModel $contractReceivableModel
     * @param bool $isComeFromBusinessSystem 是否来自商机系统
     * @return boolean|string   失败|应收款项Guid
     */
    public function saveContractReceivable($contractReceivableModel, $isComeFromBusinessSystem = false) {

        if ($contractReceivableModel->validate()) {
            if($isComeFromBusinessSystem === false){
                // 开启事务
                $configDataBase = ContractEntity::getDb();
                $trans = $configDataBase->beginTransaction();
                try{
                    if (isset($contractReceivableModel->receivable_id) && !empty($contractReceivableModel->receivable_id)) {
                        //修改
                        $resultUpdate = ContractReceivableRepository::updateContractReceivable($contractReceivableModel);
                        if($resultUpdate === false){
                            $trans->rollBack();
                            return self::setAndReturn(ContractReceivableRepository::getErrCode());
                        }
                    } else {
                        //新增
                        $resultAdd = ContractReceivableRepository::addContractReceivable($contractReceivableModel);
                        if($resultAdd === false){
                            $trans->rollBack();
                            return self::setAndReturn(ContractReceivableRepository::getErrCode());
                        }
                    }
                    //云客中成功更改了应收款时，需要向商机系统反馈
                    $resultSent = $this->sentReceivableDataToBusinessSystem($contractReceivableModel->contract_id);
                    if($resultSent === false){
                        $trans->rollBack();
                        return self::setAndReturn(__LINE__, '通知商机系统失败！');
                    }
                    $trans->commit();
                    return true;
                }catch(Exception $e){
                    $trans->rollBack();
                    return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_FORM_VERIFY_FAIL);
                }
            }else{
                //新增
                $result = ContractReceivableRepository::addContractReceivable($contractReceivableModel);
                return $result;
            }
        } else {
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_FORM_VERIFY_FAIL);
        }
    }


    /**
     * 通过新增/修改开通信息更新应收款
     * @param \common\models\myhtsq\ContractReceivableModel $contractReceivableModel
     * @param bool $isComeFromBusinessSystem 是否来自商机系统
     * @author zhoud01
     * @since 2017-7-28
     * @return boolean|string   失败|应收款项Guid
     */
    public function saveContractReceivableByEstablish($arr,$contractId) {

        // 开启事务
        $configDataBase = ContractEntity::getDb();
        $trans = $configDataBase->beginTransaction();
        try{

            $resultAdd = ContractReceivableRepository::addContractReceivableByEstablish($arr,$contractId);

            $resultSent = false;

            //云客中成功更改了应收款时，需要向商机系统反馈
            if(empty($arr)){

                return true;//空表示为初始化第一次直接放过

            }else{

                if($resultAdd === false){
                    $trans->rollBack();
                    return self::setAndReturn(__LINE__,'应收款修改失败!');
                }

                foreach ($arr as $item){
                    $resultSent = $this->sentReceivableDataToBusinessSystem($contractId);
                    if($resultSent === false){//有一次出现失败就表示失败了
                        break;
                    }

                }

            }

            //TODO 当$arr 为空表示为初始化租户开通情况 应当返回true
            if($resultSent === false){
                $trans->rollBack();
                return self::setAndReturn(__LINE__, '通知商机系统失败！');
            }
            $trans->commit();
            return true;
        }catch(Exception $e){
            $trans->rollBack();
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_FORM_VERIFY_FAIL);
        }
    }




    /**
     * 变更应收款时，调用接口更新商机系统中的应收款
     * @param $contractId
     * @return bool
     * @throws \yii\base\InvalidConfigException
     */
    public function sentReceivableDataToBusinessSystem($contractId)
    {
        if($contractId){
            /** @var ErpUserRepository $erpUserRepository */
            $erpUserRepository = \Yii::createObject(ErpUserRepository::className());

            $receivableData = $this->getReceivableInfoByContractId($contractId);

            $receivableDataToBusinessSystem = [];
            foreach($receivableData as $receivable){
                //循环，组装商机系统需要的字段
                $tmp = [];
                $tmp['GatheringGUID'] = $receivable['receivable_id'];
                $tmp['ContractGUID'] = $receivable['contract_id'];
                $tmp['ReceiveAmount'] = $receivable['receivable_amount'];//应收款金额

                $tmp['IncomeType'] = isset($receivable['revenue_type_name']) ? $receivable['revenue_type_name'] : '云客';
                $tmp['Remark']  = isset($receivable['remark'])   ? $receivable['remark']   : '';
                $tmp['FzrGUID'] = isset($receivable['payee_id']) ? $receivable['payee_id'] : '';

                //$tmp['IncomeType'] = '云客';//IncomeType这个字段改为固定值。
                $tmp['KxName'] = $receivable['receivable_item_name'];
                $tmp['KxType'] = $receivable['money_category_item_name'];
                $tmp['PayCondition'] = $receivable['payment_condition'];
                $tmp['ReceiveDate'] = $receivable['receivable_date'];
                $tmp['ParentGatheringGUID'] = $receivable['old_receivable_id'];

                $tmp['CloudJointSales'] = $receivable['unite_sales_id'];
                $cloudJoinUser = $erpUserRepository->getUserById($receivable['unite_sales_id']);
                $tmp['CloudJointSalesName'] = $cloudJoinUser['UserName'];

                $tmp['CloudSignType'] = $receivable['receivable_type'];

                $receivableDataToBusinessSystem[] = $tmp;
            }

            /** @var ErpInterfaceService $erpInterfaceService */
            $erpInterfaceService = \Yii::createObject(ErpInterfaceService::className());
            $updateBusinessSystemReceivableResult = $erpInterfaceService->updateBusinessSystemReceivable($receivableDataToBusinessSystem);
            return $updateBusinessSystemReceivableResult;
        }

        return false;
    }

    /**
     * 删除应收款信息
     * @param string $receivableId 应收款ID
     * @return boolean true删除成功/false删除失败
     */
    public function deleteContractReceivable($receivableId) {
        $entity = ContractReceivableRepository::getContractReceivableById($receivableId);
        if (!isset($entity)) {
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_NOT_EXISTS);
        }

        // 开启事务
        $configDataBase = ContractEntity::getDb();
        $trans = $configDataBase->beginTransaction();
        try{
            $affectedRowNum = $entity->delete();
            if ($affectedRowNum === false) {
                $trans->rollBack();
                return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_DELETE_FAIL);
            }
            /** @var MyscrmContractSyncDeleteDataService $myscrmContractSyncDeleteDataService */
            $myscrmContractSyncDeleteDataService = \Yii::createObject(MyscrmContractSyncDeleteDataService::className());
            $myscrmContractSyncDeleteDataService->addData('myscrm_contract_receivable', 'receivable_id', $entity->receivable_id);


            //调用商机系统API，通知商机系统修改了应收款
            $sentResult = $this->sentReceivableDataToBusinessSystem($entity->contract_id);
            if ($sentResult === false) {
                $trans->rollBack();
                return self::setAndReturn(__LINE__, '通知商机系统失败!');
            }
            $trans->commit();
        }catch(Exception $e){
            $trans->rollBack();
            return self::setAndReturn(__LINE__, (string)$e);
        }


        return true;
    }

    /**
     * 保存合同应收款项拆分信息
     * @param \common\models\myhtsq\ContractReceivableModel $contractReceivableModel
     * @return boolean|string   失败|新拆分的应收款项Guid
     */
    public function splitContractReceivable($contractReceivableModel) {
        if ($contractReceivableModel->validate()) {
            $oldEntity = ContractReceivableRepository::getContractReceivableById($contractReceivableModel->old_receivable_id);
            if (!isset($oldEntity)) {
                return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_NOT_EXISTS);
            }

            if (floatval($oldEntity['billing_amount']) > 0 || floatval($oldEntity['received_amount']) > 0) {
                return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_HAS_FAPIAO_SPLIT_FORM_VERIFY_FAIL, '当前应收款已关联了发票，不允许拆分');
            }

            // 开启事务
            $configDataBase = ContractEntity::getDb();
            $trans = $configDataBase->beginTransaction();

            try{
                //新增，记录父级的old_receivable_id
                $contractReceivableModel->old_receivable_id = $oldEntity->receivable_id;

                $resultNew = ContractReceivableRepository::addContractReceivable($contractReceivableModel);
                if ($resultNew === false) {
                    $trans->rollBack();
                    return self::setAndReturn(ContractReceivableRepository::getErrCode());
                }

                //把旧的记录内容也新增一条
                $contractReceivableModelOld = new ContractReceivableModel(['scenario' => 'splitontractreceivable']);
                $contractReceivableModelOld->receivable_amount = floatval($oldEntity->receivable_amount) - floatval($contractReceivableModel->receivable_amount);
                $contractReceivableModelOld->receivable_id = '';
                $contractReceivableModelOld->old_receivable_id = $contractReceivableModel->old_receivable_id;
                $contractReceivableModelOld->contract_id = $oldEntity->contract_id;
                $contractReceivableModelOld->receivable_item_id = $oldEntity->receivable_item_id;
                $contractReceivableModelOld->money_category_item_id = $oldEntity->money_category_item_id;
                $contractReceivableModelOld->revenue_type = $oldEntity->revenue_type;
                $contractReceivableModelOld->receivable_date = $oldEntity->receivable_date;
                $contractReceivableModelOld->payee_id = $oldEntity->payee_id;
                $contractReceivableModelOld->professional_line_id = $oldEntity->professional_line_id;
                $contractReceivableModelOld->payment_condition = $oldEntity->payment_condition;
                $contractReceivableModelOld->billing_amount = $oldEntity->billing_amount;
                $contractReceivableModelOld->received_amount = $oldEntity->received_amount;
                $contractReceivableModelOld->is_bad_debt = $oldEntity->is_bad_debt;
                $contractReceivableModelOld->is_operation = $oldEntity->is_operation;
                $contractReceivableModelOld->receivable_type = $oldEntity->receivable_type;
                $contractReceivableModelOld->remark = $contractReceivableModel->remark;
                $resultOld = ContractReceivableRepository::addContractReceivable($contractReceivableModelOld);
                if ($resultOld === false) {
                    $trans->rollBack();
                    return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_SPLIT_FAIL);
                }

                //删除旧的记录
                $resultDelete = $this->deleteContractReceivable($oldEntity->receivable_id);
                if ($resultDelete === false) {
                    $trans->rollBack();
                    return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_SPLIT_FAIL);
                }

                //调用商机系统API，通知商机系统修改了应收款
                $sentResult = $this->sentReceivableDataToBusinessSystem($oldEntity->contract_id);
                if ($sentResult === false) {
                    $trans->rollBack();
                    return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_SENT_BUSSENISS_FAIL, '通知商机系统失败!');
                }

                $trans->commit();

                return true;
            }catch(Exception $e){
                $trans->rollBack();
                return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_SPLIT_FORM_VERIFY_FAIL);
            }
        } else {
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_SPLIT_FORM_VERIFY_FAIL);
        }
    }

    /**
     * 保存合同应收款项责任人变更信息
     * @param \common\models\myhtsq\ContractReceivableModel $contractReceivableModel
     * @return boolean|string   失败|应收款项Guid
     */
    public function changeResponsiblePerson($contractReceivableModel)
    {
        if ($contractReceivableModel->validate()) {
            //修改
            $result = ContractReceivableRepository::updateContractReceivable($contractReceivableModel);
            if ($result === false) {
                return self::setAndReturn(ContractReceivableRepository::getErrCode());
            }

            //调用商机系统API，通知商机系统修改了应收款
            $sentResult = $this->sentReceivableDataToBusinessSystem($contractReceivableModel->contract_id);
            if ($sentResult === false) {
                return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_SENT_BUSSENISS_FAIL, '通知商机系统失败!');
            }

            return $result;
        } else {
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_CHANGE_RESPONSIBLE_FORM_VERIFY_FAIL);
        }
    }

    /**
     * 保存合同应收款项名称变更信息
     * @param \common\models\myhtsq\ContractReceivableModel $contractReceivableModel
     * @return boolean|string   失败|应收款项Guid
     */
    public function changeResponsibleItem($contractReceivableModel)
    {
        if ($contractReceivableModel->validate()) {
            //修改
            $result = ContractReceivableRepository::updateContractReceivable($contractReceivableModel);
            if ($result === false) {
                return self::setAndReturn(ContractReceivableRepository::getErrCode());
            }
            return $result;
        } else {
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_CHANGE_RESPONSIBLE_FORM_VERIFY_FAIL);
        }
    }

    /**
     * 保存合同应收关联收入项变更信息
     * @param \common\models\myhtsq\ContractReceivableModel $contractReceivableModel
     * @return boolean|string   失败|应收款项Guid
     */
    public function changeResponsibleRevenueType($contractReceivableModel)
    {
        if ($contractReceivableModel->validate()) {
            //修改
            $result = ContractReceivableRepository::updateContractReceivable($contractReceivableModel);
            if ($result === false) {
                return self::setAndReturn(ContractReceivableRepository::getErrCode());
            }
            return $result;
        } else {
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_CHANGE_RESPONSIBLE_FORM_VERIFY_FAIL);
        }
    }
    
    /**
     * 保存合同应收款项应收时间变更信息
     * @param \common\models\myhtsq\ContractReceivableModel $contractReceivableModel
     * @return boolean|string   失败|应收款项Guid
     */
    public function changeReceivableDate($contractReceivableModel) {
        if ($contractReceivableModel->validate()) {
            //修改
            // 开启事务
            $configDataBase = ContractEntity::getDb();
            $trans = $configDataBase->beginTransaction();
            try {
                $result = ContractReceivableRepository::updateContractReceivable($contractReceivableModel);
                if ($result === false) {
                    $trans->rollBack();
                    return self::setAndReturn(ContractReceivableRepository::getErrCode());
                }

                $resultSent = $this->sentReceivableDataToBusinessSystem($contractReceivableModel->contract_id);
                if($resultSent === false){
                    $trans->rollBack();
                    return self::setAndReturn(__LINE__, '通知商机系统失败！');
                }

                $trans->commit();
                return $result;
            }catch(Exception $e){
                $trans->rollBack();
                return self::setAndReturn(__LINE__, (string)$e);
            }
        } else {
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_CHANGE_RECEIVABLE_DATE_FORM_VERIFY_FAIL);
        }
    }


    /**
     * 更新应收款其他相关字段
     * @param $receivableId
     * @param $data
     * @return bool|string
     */
    public function updateReceivableField($receivableId, $data)
    {
        return ContractReceivableRepository::updateContractReceivableField($receivableId, $data);
    }

    /**
     * 将合同应收款标记为坏账
     * @param string $receivableId 应收款ID
     * @param string $isBadDebt 是否坏账 0：否，1：是
     * @param string $badDebtReason 坏账原因
     * @return boolean true更新成功/false 更新失败
     */
    public function markBadDebt($receivableId, $isBadDebt, $badDebtReason = '') {
        $entity = ContractReceivableRepository::getContractReceivableById($receivableId);
        if (!isset($entity)) {
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_NOT_EXISTS);
        }

        $entity->is_bad_debt = $isBadDebt;
        $entity->bad_debt_reason = $badDebtReason;
        $entity->bad_debt_date = date('Y-m-d H:i:s');
        $affectedRowNum = $entity->update();
        if ($affectedRowNum === false) {
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_MARK_BAD_DEBT_FORM_SAVE_FAIL);
        }

        return true;
    }

    /**
     * 将合同应收款标记为运营关注
     * @param string $receivableId  应收款ID
     * @param string $isOperation 是否运营关注项 0：否，1：是
     * @return boolean true更新成功/false 更新失败
     */
    public function markOperation($receivableId, $isOperation) {
        $entity = ContractReceivableRepository::getContractReceivableById($receivableId);
        if (!isset($entity)) {
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_NOT_EXISTS);
        }

        $entity->is_operation = $isOperation;
        $affectedRowNum = $entity->update();
        if ($affectedRowNum === false) {
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_MARK_OPERATION_FORM_SAVE_FAIL);
        }

        return true;
    }

    /**
     * 如果引入的是红冲发票，则需要判断已开票金额够不够减
     * @param $invoiceModel \common\models\myhtsq\InvoiceModel $invoiceModel
     * @return bool
     */
    public function checkRedInvoiceAmount($invoiceModel)
    {
        $receivableSum = 0;

        if(!empty($invoiceModel->invoiceReceivables)) {
            foreach ($invoiceModel->invoiceReceivables as $receivable) {
                $receivableEntity = ContractReceivableRepository::getReceivableEntity($receivable['receivable_id']);

                if ($receivableEntity) {
                    $receivableSum += floatval($receivableEntity->billing_amount);
                }
            }
        }

        if($invoiceModel->invoice_amount < 0){
            $result = $invoiceModel->invoice_amount + $receivableSum;
            if($result < 0){
                return self::setAndReturn(__LINE__, '引入红冲发票时，已开票金额不能小于0');
            }
        }

        return true;
    }

    /**
     * 保存发票信息（与应收款的关系）
     * @param \common\models\myhtsq\InvoiceModel $invoiceModel
     * @return boolean|string   失败|发票Guid
     */
    public function saveInvoiceReceivable($invoiceModel) {
        if ($invoiceModel->validate()) {

            // 收据号码不为空时重复判断
            if (($invoiceModel->is_red_invoice != 1 && $invoiceModel->is_reded_invoice != 1) && !empty($invoiceModel->invoice_no) && InvoiceService::exitSameInvoiceNo($invoiceModel->invoice_no, $invoiceModel->invoice_id)) {
                return $invoiceModel->is_receipt == 1 ? self::setAndReturn(ErrorCode::ERR_RECEIPT_NO_EXIST_SAME) : self::setAndReturn(ErrorCode::ERR_INVOICE_NO_EXIST_SAME); 
            }

            // 开启事务
            $configDataBase = ContractEntity::getDb();
            $trans = $configDataBase->beginTransaction();

            //数据来自同步接口，则需要映射开票单位
            if(isset($invoiceModel->is_sync) && $invoiceModel->is_sync == 1){
                $this->fillInvoiceBusinessUnit($invoiceModel);
            }

            if (isset($invoiceModel->invoice_id) && !empty($invoiceModel->invoice_id)) {
                //修改
                $invoiceModel->is_import = 5; //5：合同管理收据转发票
                $result = InvoiceRepository::updateInvoice($invoiceModel);
            } else {
                //新增
              if($invoiceModel->is_sync == 1) {         //ekp接口同步过来的

                   $receipt = InvoiceRepository::getReceiptByContractId($invoiceModel->contract_id, $invoiceModel->invoice_amount);
                   if(empty($receipt)){
                       $invoiceModel->is_import = 4;    // 4: ekp新增发票
                       $invoiceModel->created_by = 'ekp';
                       $invoiceModel->modified_by = 'ekp';
                       $result = InvoiceRepository::addInvoice($invoiceModel);
                   }else{

                       $receipt->is_receipt = 0;
                       $receipt->invoice_code = $invoiceModel->invoice_code;
                       $receipt->invoice_no = $invoiceModel->invoice_no;
                       $receipt->is_import = 3;                              // 3: ekp收据转发票
                       $receipt->invoice_date = $invoiceModel->invoice_date; //开票时间与ekp做同步
                       $receipt->modified_by = 'ekp';                        //修改人变成ekp
                       $result = $receipt->save();

                       if ($result === false) {
                           // 回滚事务
                           $trans->rollBack();
                           return self::setAndReturn(InvoiceSummaryRepository::getErrCode());
                       }

                       // 提交事务
                       $trans->commit();
                       return $receipt->invoice_id;
                   }

                }else{
                  $result = InvoiceRepository::addInvoice($invoiceModel);
                }

            }

            if ($result === false) {
                // 回滚事务
                $trans->rollBack();
                return self::setAndReturn(InvoiceRepository::getErrCode());
            } else {
                // 子发票的所有开票金额不能大于主发票的开票金额
                if ($invoiceModel->is_child_invoice == 1 && !empty($invoiceModel->main_invoice_id)) {
                    $res = InvoiceService::checkMainInvoiceAmountMorethanChildAmount($invoiceModel->main_invoice_id);
                    if ($res !== true) {
                        // 回滚事务
                        $trans->rollBack();
                        return ErrorInfo::setAndReturn(ErrorCode::ERR_INVOICE_FORM_SAVE_FAIL, '', '子发票的所有开票金额不能大于主发票的开票金额');
                    }
                }
                // 先删除原有的发票摘要
                $res = InvoiceSummaryRepository::deleteInvoiceSummaryByInvoiceId($result);
                if ($res !== true) {
                    // 回滚事务
                    $trans->rollBack();
                    return self::setAndReturn(InvoiceSummaryRepository::getErrCode());
                }

                // 再新增现有的发票摘要
                $invoiceSummarys = $invoiceModel->invoiceSummarys;
                if (isset($invoiceSummarys) && count($invoiceSummarys) > 0) {
                    foreach ($invoiceSummarys as $k => $v) {
                        $v['invoice_id'] = $result;
                        $v['summary_id'] = NULL;
                        $model = new InvoiceSummaryModel();
                        $model->load($v, '');
                        $res = InvoiceSummaryRepository::addInvoiceSummary($model);
                        if ($res === false) {
                            // 回滚事务
                            $trans->rollBack();
                            return self::setAndReturn(InvoiceSummaryRepository::getErrCode());
                        }
                    }
                }

                // 保存文档记录
                $invoiceDocuments = $invoiceModel->invoiceDocuments;
                if (isset($invoiceDocuments) && count($invoiceDocuments) > 0) {
                    foreach ($invoiceDocuments as $k => $v) {

                        if ($invoiceModel->is_red_invoice == 1) {
                            $v ['__type'] = 'add';
                        }elseif (!isset($v ['__type'])) {
                            $v ['__type'] = 'update';
                        }

                        switch ($v ['__type']) {
                            case 'delete' :
                                $res = DocumentRepository::delDocumentById($v['document_id']);
                                if ($res === false) {
                                    // 回滚事务
                                    $trans->rollBack();
                                    return self::setAndReturn(DocumentRepository::getErrCode());
                                }
                                break;
                            case 'add' :
                                $documentModel = new DocumentModel();
                                $documentModel->setAttributes($v);
                                $explode = explode('.', $v['document_name']);
                                $extName = end($explode);
                                $documentModel->document_ext_name = $extName;
                                $documentModel->business_id = $result;
                                if ($documentModel->validate()) {
                                    DocumentRepository::addDocument($documentModel);
                                    if ($res === false) {
                                        // 回滚事务
                                        $trans->rollBack();
                                        return self::setAndReturn(DocumentRepository::getErrCode());
                                    }
                                }
                                break;
                        }
                    }
                }

                // 保存发票与应收款的对应关系
                $invoiceReceivables = $invoiceModel->invoiceReceivables;
                if (isset($invoiceReceivables) && count($invoiceReceivables) > 0) {

                    //数据来自同步接口，则需要计算cur_billing_amount字段
                    if(isset($invoiceModel->is_sync) && $invoiceModel->is_sync == 1){
                        $this->fillCurBillingAmount($invoiceReceivables, $invoiceModel);
                    }

                    foreach ($invoiceReceivables as $k => $v) {
                        if (floatval($v['cur_billing_amount']) == 0) {
                            continue;
                        }

                        $v['invoice_id'] = $result;
                        $res = InvoiceReceivableRepository::saveInvoiceReceivable($v);
                        if ($res === false) {
                            // 回滚事务
                            $trans->rollBack();
                            return self::setAndReturn(InvoiceReceivableRepository::getErrCode());
                        }

                        // 重新刷新应收款的billing_amount
                        $res = self::summaryReceivablesAmount($v['receivable_id']);
                        if ($res === false) {
                            // 回滚事务
                            $trans->rollBack();
                            return self::setAndReturn(self::getErrCode());
                        }
                    }
                }

                // 如果是红冲发票
                if ($invoiceModel->is_red_invoice == 1 && $invoiceModel->is_sync == 1) {
                    $res = $this->setPassiveRedInvoiceInfo($invoiceModel->red_by_invoice_id, $result);
                    if (!$res) {
                        // 回滚事务
                        $trans->rollBack();
                        return self::setAndReturn(ErrorCode::ERR_INVOICE_FORM_SAVE_FAIL);
                    }
                }

                // 重新刷新发票的receivable_amount
                $res = InvoiceService::summaryReceivablesAmount($result);
                if (!$res) {
                    // 回滚事务
                    $trans->rollBack();
                    return self::setAndReturn(InvoiceService::getErrCode());
                }

                // 重新刷新发票的payment_amount
                $res = InvoiceService::summaryInvoicePaymentAmount($result);
                if (!$res) {
                    // 回滚事务
                    $trans->rollBack();
                    return self::setAndReturn(InvoiceService::getErrCode());
                }

                // 提交事务
                $trans->commit();

                return $result;
            }
        } else {
            return self::setAndReturn(ErrorCode::ERR_INVOICE_FORM_VERIFY_FAIL);
        }
    }

    /**
     * 同步接口同步过来的数据需要计算cur_billing_amount字段值
     * @param array $invoiceReceivables
     * @param \common\models\myhtsq\InvoiceModel $invoiceModel
     */
    private function fillCurBillingAmount(&$invoiceReceivables, $invoiceModel)
    {
        $invoiceAmount = floatval($invoiceModel->invoice_amount);

        foreach ($invoiceReceivables as &$row) {

            //发票金额小于等于0时跳过
            if($invoiceAmount <= 0){
                continue;
            }

            $receivableEntity = $this->getContractReceivableEntity($row['receivable_id']);
            $receivableAmount = isset($receivableEntity->receivable_amount) ? floatval($receivableEntity->receivable_amount) : 0;

            $row['cur_billing_amount'] = $invoiceAmount > $receivableAmount ? $receivableAmount : $invoiceAmount;

            //减去已填充的值
            $invoiceAmount = $invoiceAmount - $receivableAmount;
        }
    }

    /**
     * 根据应收款ID重新刷新应收款的已开票金额(billing_amount)
     * @param string $receivableId 应收款id
     * @return boolean true刷新成功/false刷新失败
     */
    public static function summaryReceivablesAmount($receivableId) {
        $totalAmount = 0;
        $contractReceivable = ContractReceivableRepository::getContractReceivableById($receivableId);
        if (!isset($contractReceivable)) {
            return true;
            //return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_NOT_EXISTS);
        }

        $invoiceReceivables = InvoiceReceivableRepository::getInvoiceReceivablesByReceivableId($receivableId);
        if (isset($invoiceReceivables) && count($invoiceReceivables)) {
            foreach ($invoiceReceivables as $k => $v) {
                $totalAmount += floatval($v['cur_billing_amount']);
            }
        }

        $contractReceivable->billing_amount = $totalAmount;
        $result = $contractReceivable->update();
        if ($result === false) {
            return $result;
        }

        return true;
    }

    /**
     * 重新刷新应收款的已收金额(received_amount)
     * @param string $receivableId 应收款ID
     * @return boolean true刷新成功/false刷新失败
     */
    public static function summaryContractReceivableReceivedAmount($receivableId) {
        $contractReceivable = self::getContractReceivableEntity($receivableId);

        if (!isset($contractReceivable)) {
            return false;
        }

        $totalPaymentAmount = InvoicePaymentRepository::getTotalPaymentAmountByReceivableId($receivableId);
        $contractReceivable->received_amount = $totalPaymentAmount;
        $affectedRowNum = $contractReceivable->update();

        if ($affectedRowNum === false) {
            return false;
        }

        return true;
    }

    /**
     * 设置被红冲发票的相关信息
     * 清空被红冲发票中的receivables_amount、payment_amount
     * 删除myscrm_invoice_payment对应的记录
     * 删除myscrm_invoice_receivable对应的记录
     * 重新刷新对应应收款中的billing_amount、received_amount
     * @param string $invoiceId 被红冲发票ID
     * @param string $redInvoiceId 红冲发票ID
     * @return boolean true刷新成功/false刷新失败
     */
    private function setPassiveRedInvoiceInfo($invoiceId, $redInvoiceId) {
        $invoice = InvoiceService::getInvoiceEntity($invoiceId);
        if (!isset($invoice)) {
            return self::setAndReturn(ErrorCode::ERR_INVOICE_NOT_EXISTS);
        }

        // 1、将被红冲发票的receivables_amount、payment_amount都设置成0
        $invoice->receivables_amount = 0;
        $invoice->payment_amount = 0;
        $invoice->red_by_invoice_id = $redInvoiceId;
        $result = $invoice->update();
        if ($result === false) {
            return self::setAndReturn(ErrorCode::ERR_INVOICE_FORM_SAVE_FAIL);
        }

        // 获取发票下的所有应收款
        $receivableIds = [];
        $invoiceReceivables = InvoiceReceivableRepository::getInvoiceReceivablesByInvoiceId($invoiceId);
        if (isset($invoiceReceivables) && count($invoiceReceivables) > 0) {
            foreach ($invoiceReceivables as $k => $v) {
                $receivableIds[] = $v['receivable_id'];
                // 2、删除myscrm_invoice_payment对应的记录
                $result = InvoicePaymentRepository::deleteInvoicePaymentByInvoiceReceivableId($v['invoice_receivable_id']);
                if (!$result) {
                    return self::setAndReturn(ErrorCode::ERR_INVOICE_FORM_SAVE_FAIL);
                }
            }
        }

        // 3、删除myscrm_invoice_receivable对应的记录
        $result = InvoiceReceivableRepository::deleteInvoiceReceivableByInvoiceId($invoiceId);
        if (!$result) {
            return self::setAndReturn(ErrorCode::ERR_INVOICE_FORM_SAVE_FAIL);
        }

        // 4、更新合同应收款中的billing_amount、received_amount
        foreach ($receivableIds as $k => $v) {
            $contractReceivableEntity = ContractReceivableRepository::getContractReceivableById($v);
            if (isset($contractReceivableEntity)) {
                $billingAmount = InvoiceReceivableRepository::getTotalBillingAmountByReceivableId($v);
                $receivedAount = InvoicePaymentRepository::getTotalPaymentAmountByReceivableId($v);

                $contractReceivableEntity->billing_amount = $billingAmount;
                $contractReceivableEntity->received_amount = $receivedAount;
                $result = $contractReceivableEntity->update();
                if ($result === false) {
                    return self::setAndReturn(ErrorCode::ERR_INVOICE_FORM_SAVE_FAIL);
                }
            }
        }

        return true;
    }

    /**
     * 根据应收款项Id获取对应的应收款
     * @param string $receivableId 应收款项Id
     * @return \common\entities\myhtsq\ContractReceivableEntity
     */
    public static function getContractReceivableEntity($receivableId) {
        return ContractReceivableRepository::getContractReceivableById($receivableId);
    }

    /**
     * 根据合同ID获取对应的发票与应收款对应关系
     * @param string $contractId
     * @return array
     */
    public function getInvoiceReceivableInfoByContractId($contractId) {
        $invoiceReceivableInfos = InvoiceReceivableRepository::getInvoiceReceivablesByContractId($contractId);
        if (isset($invoiceReceivableInfos) && count($invoiceReceivableInfos) > 0) {
            // 叠加回款信息
            foreach ($invoiceReceivableInfos as $k => $v) {
                $totalPayment = 0;
                $financeCode = [];
                $invoicePayments = InvoicePaymentRepository::getInvoicePaymentByInvoiceReceivableId($v['invoice_receivable_id']);
                if (isset($invoicePayments) && count($invoicePayments) > 0) {
                    foreach ($invoicePayments as $k1 => $v1) {
                        $totalPayment += floatval($v1['cur_payment_amount']);
                        if (!in_array($v1['finance_code'], $financeCode)) {
                            $financeCode[] = $v1['finance_code'];
                        }
                    }
                }

                $invoiceReceivableInfos[$k]['total_payment'] = $totalPayment;
                $invoiceReceivableInfos[$k]['finance_code'] = implode(';', $financeCode);
            }
        }

        return $invoiceReceivableInfos;
    }

    /**
     * 应收时间到期前7天
     */
    public function receivableExpiredRemind(){
        $expiredDate = date_add(date_create_from_format('Y-m-d H:i:s', ContractEntity::getDbNowDate()), \DateInterval::createFromDateString('7 Day'));
        $expiredDate = date_format($expiredDate, 'Y-m-d');
        //获取7天到期的应收款
        $expiredReceivables = ContractReceivableRepository::getReceivableExpiredRemind($expiredDate);
        foreach($expiredReceivables as $key=>$item){
            //获取合同累计回款金额
            $totalRefundAmount = InvoicePaymentRepository::getTotalPaymentAmountByContractId($item['contract_id']);
            //获取合同信息
            $contractInfo = ContractManageRepository::getContractManageModelByContractId($item['contract_id']);
            $emailParams = [
                'contractId'            => $contractInfo->contract_code,
                'custName'              => $contractInfo->customer_name,
                'contractAmount'        => $contractInfo->sign_amount,
                'receivableAmount'      => $item['receivable_amount'],
                'totalReceivedAmount'   => $totalRefundAmount,
                'receivableDate'        => $item['receivable_date']
            ];
            $this->sendEmail($item['payee_id'], '【合同管理】应收信息', 'receivableExpired', $emailParams, []);
        }

    }

    private function sendEmail($userId, $subject, $template, $params, $cc)
    {
        $user = ErpUserRepository::getUserById($userId);
        if (empty($user)) {
            return;
        }
        //获取抄送人
        $copyToEMail = ContractEmailContactsRepository::getCCContactsByBu($user['BUGUID'], $user['UserCode']);

        $params['ScrmUrl'] = \Yii::$app->params['ScrmUrl'];
        $params['userName'] = $user['UserName'];

        if (is_array($cc)) {
            $copyToEMail = array_merge($copyToEMail,$cc);
        }
        $params['ScrmUrl'] = \Yii::$app->params['ScrmUrl'];
        return EmailService::sendEMail([$user['Email']=>$user['UserName']], $subject, 'contract/' .$template, $params, $copyToEMail);
    }

    /**
     * 处理开票单位映射关系
     * @param \common\models\myhtsq\InvoiceModel $invoiceModel
     */
    private function fillInvoiceBusinessUnit(&$invoiceModel)
    {
        if(isset($invoiceModel->invoice_company_id) && !empty($invoiceModel->invoice_company_id)){
            $erpCompanyId = $invoiceModel->invoice_company_id;

            /** @var InvoiceService $invoiceBusinessUnitService */
            $invoiceBusinessUnitService = \Yii::createObject(InvoiceService::className());

            $unit = $invoiceBusinessUnitService->getInvoiceBusinessUnitByErpGuid($erpCompanyId);
            if($unit){
                $invoiceModel->invoice_company_id = $unit->BUGUID;
            }
        }
    }
}
